package com.atguigu.gmall.pms.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * 给rabbitTemplate配置生产者确认：消息到达交换机的确认，消息到达队列的确认
 *                                消息出问题方便在控制台查找在哪里出的问题
 * 目的： 方便监管mq消息。当消息未到达交换机或者队列时，在控制台打印相对应的错误原因
 * 实现方式：利用配置类，对rabbitTemplate对象进行，方法增强，当rabbitTemplate被创建后，立刻执行init方法
 *           在init方法中写上 打印错误原因 的代码
 */
@Configuration
@Slf4j
public class MqConfig {


    @Autowired
    private RabbitTemplate rabbitTemplate;

    //使用jdk的注解，在当前类的对象实例化之后，立即对rabbitTemplate进行配置
    //原理：当前类对象实例化好了，那么成员变量rabbitTemplate肯定初始化好了，
    //      初始化好后，我们这个方法立即执行，对rabbitTemplate进行配置，这样我们就对rabbitTemplate进行配置了。
    @PostConstruct//构造器调用之后，立即调用此方法，spring的bean的生命周期也有类似注解，bean被创建后立即执行某某方法
    public void init() {//这个方法名随意
        //消息到达队列时候的确认
        //消息未到队列时回调
        rabbitTemplate.setReturnCallback((Message message, int replyCode, String replyText, String exchange, String routingKey) -> {
            log.error("------消息未到达队列：" + exchange + ",路由key：" + routingKey + ",应答码：" +
                    replyCode + ",原因：" + replyText + ",消息：" + message.getBody());
        });


        //消息未到达交换机时候的确认
        //消息未到达交换机时回调
        //只有ack=false的时候，说明消息未到达交换机。这时候correlationData、cause才有值
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (!ack) {
                log.error("------消息未到达交换机，原因：" + cause);
            }
        });
    }


}
